home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / romable.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  12KB  |  568 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7.  *  $Id: romable.c,v 30.326 1995/12/24 06:13:05 dice Exp dice $
  8.  *
  9.  *  Romable exefile -o outfile [-o outfile2] [-pi] [-C addr -D addr]
  10.  *
  11.  */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15.  
  16. #ifdef AMIGA
  17. #include <lib/version.h>
  18. #else
  19. #include <suplib/memory.h>
  20. #include <include/lib/version.h>
  21. #include <unistd.h>
  22. #endif
  23.  
  24. #define D(x)    ;    /* Debugging Disabled */
  25. /* #define D(x)    x;       // Debugging Enabled */
  26.  
  27. /* #define    BSS_IN_OUTPUT_FILE    // Write zeros to output file for BSS */
  28.  
  29. long    NumHunks;
  30. long    FirstHunk;
  31. long    LastHunk;
  32.  
  33. long    CodeStart;
  34. long    DataStart;
  35. short    DataStartAfterCode = 0;
  36. char    DataStartSpecified;    /*    flag, argument specified */
  37. char    CodeStartSpecified;    /*    flag, argument specified */
  38. char    PIOpt;            /*    -pi (position independent) */
  39.  
  40. int    _bufsiz = 8192;     /*    Buffered file I/O */
  41.  
  42. typedef unsigned char ubyte;
  43.  
  44. /*
  45. **    One of these is allocated per hunk in the file.
  46. */
  47. typedef struct {
  48.     long    Type;    /* AmigaDOS hunk type */
  49.     long    Len;    /* Initialized data length only */
  50.     long    Pc;
  51.     char    *Data;    /* Allocated memory for hunk */
  52. } Hunk;
  53.  
  54. Hunk    *Hunks;
  55.  
  56. long    fgetl(FILE *);
  57. void    LoadHeaderInfo(FILE *);
  58. void    ScanHunks(FILE *);
  59. void    RelocHunks(FILE *);
  60. void    DumpHunks(FILE *, FILE *);
  61. int    fwrite_2(int, FILE *, FILE *, char *, long);
  62.  
  63. int
  64. main(int ac, char **av)
  65. {
  66.     short i;
  67.     char *inFile = NULL;
  68.     char *outFile1= NULL;
  69.     char *outFile2= NULL;
  70.     FILE *fi;
  71.     FILE *fo1;
  72.     FILE *fo2 = NULL;
  73.  
  74.  
  75.     if (ac == 1 || ( ac == 2  &&  *av[1]=='?' )  ) {
  76.     puts("Romable input.exe -o out_even [-o out_odd] -C 0xADDR -D[C] 0xADDR -pi");
  77.     puts(";Convert Amiga executable files into binary files");
  78.     exit(1);
  79.     }
  80.  
  81.     for (i = 1; i < ac; ++i) {
  82.     char *ptr = av[i];
  83.     char *dummy;
  84.  
  85.     if (*ptr != '-') {
  86.         inFile = ptr;
  87.         continue;
  88.     }
  89.     ptr += 2;
  90.     switch(ptr[-1]) {
  91.     case 'o':
  92.         if (*ptr == 0)
  93.         ptr = av[++i];
  94.  
  95.         if (outFile1 == NULL) {
  96.         outFile1 = ptr;
  97.         } else if (outFile2 == NULL) {
  98.         outFile2 = ptr;
  99.         } else {
  100.         puts("Only two image files may be specified");
  101.         exit(1);
  102.         }
  103.         break;
  104.     case 'p':   /*  -pi */
  105.         PIOpt = 1;        /*    position independant    */
  106.         break;
  107.     case 'C':
  108.         if (*ptr == 0)
  109.         ptr = av[++i];
  110.         CodeStart = strtol(ptr, &dummy, 0);
  111.         CodeStartSpecified = 1;
  112.         break;
  113.     case 'D':
  114.         if (*ptr == 'C') {
  115.         DataStartSpecified = 1;
  116.         DataStartAfterCode = 1;
  117.         break;
  118.         }
  119.         if (*ptr == 0)
  120.         ptr = av[++i];
  121.         DataStart = strtol(ptr, &dummy, 0);
  122.         DataStartSpecified = 1;
  123.         break;
  124.     default:
  125.         printf("Bad option: %s\n", av[i]);
  126.         exit(1);
  127.     }
  128.     }
  129.     if (i > ac) {
  130.     puts("Expected argument");
  131.     exit(1);
  132.     }
  133.     if (PIOpt) {
  134.     DataStart = 0;        /*    all relative accesses    */
  135.     CodeStart = 0;
  136.     DataStartSpecified = 1;
  137.     CodeStartSpecified = 1;
  138.     } else {
  139.     if (DataStartSpecified == 0 || CodeStartSpecified == 0) {
  140.         puts("-D and/or -C options not specified!");
  141.         exit(1);
  142.     }
  143.     }
  144.     if (inFile == NULL) {
  145.     puts("Expected input file");
  146.     exit(1);
  147.     }
  148.     if (outFile1 == NULL) {
  149.     puts("Expected output file");
  150.     exit(1);
  151.     }
  152.     fi = fopen(inFile, "r");
  153.     if (fi == NULL) {
  154.     printf("Unable to open input file %s\n",inFile);
  155.     exit(1);
  156.     }
  157.     if (fgetl(fi) != 0x3F3) {
  158.     printf("%s is not an executable",inFile);
  159.     exit(1);
  160.     }
  161.  
  162.     /*
  163.      *    skip name
  164.      */
  165.     {
  166.     int n = fgetl(fi);
  167.     while (n--)
  168.         fgetl(fi);
  169.     }
  170.  
  171.     /*
  172.      *    header info
  173.      */
  174.  
  175.     NumHunks    = fgetl(fi);
  176.     FirstHunk    = fgetl(fi);
  177.     LastHunk    = fgetl(fi);
  178.  
  179.     Hunks = malloc(NumHunks * sizeof(Hunk));
  180.     if (Hunks == NULL) {
  181.     puts("malloc failed");
  182.     exit(1);
  183.     }
  184.     LoadHeaderInfo(fi);
  185.     {
  186.     long pos = ftell(fi);
  187.         D(puts("--scan--"));
  188.  
  189.     ScanHunks(fi);
  190.  
  191.     fseek(fi, pos, 0);
  192.         D(puts("--reloc--"));
  193.  
  194.     RelocHunks(fi);
  195.     }
  196.     fclose(fi);
  197.  
  198.     fo1 = fopen(outFile1, "w");
  199.     if (fo1 == NULL) {
  200.     printf("Unable to open output file %s\n", outFile1);
  201.     exit(1);
  202.     }
  203.     if (outFile2) {
  204.     fo2 = fopen(outFile2, "w");
  205.     if (fo2 == NULL) {
  206.         printf("Unable to open output file %s\n", outFile2);
  207.         fclose(fo1);
  208.         remove(outFile1);
  209.         exit(1);
  210.     }
  211.     }
  212.     D(puts("--dump--"));
  213.     DumpHunks(fo1, fo2);
  214.     fclose(fo1);
  215.     if (fo2)
  216.     fclose(fo2);
  217.     return(0);
  218. }
  219.  
  220. void
  221. LoadHeaderInfo(fi)
  222. FILE *fi;
  223. {
  224.     int n;
  225.     Hunk *h;
  226.  
  227.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  228.     h->Len = fgetl(fi) * 4;
  229.     h->Data= malloc(h->Len + 1);    /*  +1 so can malloc 0 wo/error    */
  230.     if (h->Data == NULL) {
  231.         printf("malloc failed [hunk %d,length %ld]\n", n, h->Len);
  232.         exit(1);
  233.     }
  234.     }
  235. }
  236.  
  237. long    CodePc;
  238. long    DataPc;
  239.  
  240. /*
  241.  *  Determine PC start and TYPE.  Read data into preallocated memory.
  242.  */
  243.  
  244. void
  245. ScanHunks(fi)
  246. FILE *fi;
  247. {
  248.     int n;
  249.     Hunk *h;
  250.  
  251.     n = 0;
  252.     h = Hunks;
  253.     while (n < NumHunks) {
  254.     long len;
  255.     long blen;
  256.     long t = fgetl(fi);
  257.  
  258.         D(printf("Header %08lx\n", t));
  259.  
  260.     switch(t) {
  261.     case 0x3E9:    /*  CODE    */
  262.     case 0x3EA:    /*  DATA    */
  263.         h->Type = t;
  264.         len = fgetl(fi) * 4;
  265.         if (len > h->Len || len < 0) {
  266.         printf("Hunk Error: Text len %ld/%ld\n", len, h->Len);
  267.         exit(1);
  268.         }
  269.         h->Len = len;
  270.         if (fread(h->Data, 1, (size_t)len, fi) != len) {
  271.         puts("Unexpected EOF");
  272.         exit(1);
  273.         }
  274.         break;
  275.     case 0x3EB:    /*  BSS     */
  276.         D(printf("BSS Length=%d\n",h->Len));
  277.         h->Type = t;
  278.         setmem(h->Data, h->Len, 0);
  279.         if ((blen=(fgetl(fi)*4)) != h->Len)
  280.         printf("Size mismatch on BSS hunk #%d: %ld != %ld\n",n,blen,h->Len);
  281.         break;
  282.     case 0x3EC:    /*  HUNK_RELOC32    */
  283.         while ((len = fgetl(fi) * 4) != 0) {
  284.             D(printf("Reloc 32 len = %d\n", len));
  285.         fgetl(fi);    /*  skip hunk#    */
  286.         fseek(fi, len, 1);
  287.         }
  288.         break;
  289.     case 0x3F0:    /*  SYMBOLS */
  290.         /*
  291.          *    ignore
  292.          */
  293.         while ((len = fgetl(fi)) != 0) {
  294.         ubyte type = len >> 24;
  295.  
  296.         len &= 0x00FFFFFF;
  297.         fseek(fi, len * 4, 1);
  298.  
  299.         switch(type) {
  300.         case 0:     /*  SYMB    */
  301.         case 1:     /*  DEF     */
  302.         case 2:     /*  ABS     */
  303.         case 3:     /*  RES     */
  304.             fgetl(fi);
  305.             break;
  306.         case 130:    /*  COMMON  */
  307.             puts("COMMON symbol not supported");
  308.             fgetl(fi);    /*  skip common size */
  309.             /* fall through */
  310.         case 129:    /*  REF32   */
  311.         case 131:    /*  REF16   */
  312.         case 132:    /*  REF8    */
  313.         case 134:    /*  REF16D  */
  314.                 /*  skip relocation info */
  315.             fseek(fi, fgetl(fi) * 4 + 4, 1);
  316.             break;
  317.         default:
  318.             printf("Symbol type %d unknown\n", type);
  319.             exit(1);
  320.         }
  321.         }
  322.         break;
  323.     case 0x3F2:    /*  ignore HUNK_END */
  324.         ++n;
  325.         ++h;
  326.         break;
  327.     default:
  328.         printf("Hunk type %08lx unknown\n", (unsigned long)h->Type);
  329.         exit(1);
  330.     }
  331.     }
  332.  
  333.  
  334.     CodePc = CodeStart;
  335.  
  336.     /*
  337.      *    Calculate CODE PC's (base of each hunk, based on size of other hunks)
  338.      */
  339.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  340.     if (h->Type == 0x3E9) {
  341.         D(printf("Code hunk: CodePc=%lx\n",CodePc));
  342.         h->Pc = CodePc;
  343.         CodePc += h->Len;
  344.     }
  345.     }
  346.     D(printf("Code end : CodePc=%lx\n",CodePc));
  347.  
  348.     /*
  349.      *    DATA PC's.  If -DC (data start after code) is specified then
  350.      *            jam the now determined address in (no duplication
  351.      *            of data occurs in this case)
  352.      */
  353.     if (DataStartAfterCode)
  354.     DataStart = CodePc;
  355.  
  356.     DataPc = DataStart;
  357.  
  358.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  359.     if (h->Type == 0x3EA) {
  360.         D(printf("Data hunk: DataPc=%lx\n",DataPc));
  361.         h->Pc = DataPc;
  362.         DataPc += h->Len;
  363.         CodePc += h->Len;
  364.     }
  365.     }
  366.  
  367.     /*
  368.      *    Start BSS at the end of data
  369.      */
  370.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  371.     if (h->Type == 0x3EB) {
  372.         D(printf("BSS hunk : DataPc=%lx\n",DataPc));
  373.         h->Pc = DataPc;
  374.         DataPc += h->Len;
  375.     }
  376.     }
  377.     D(printf("Data/BSS end : DataPc=%lx\n",DataPc));
  378. }
  379.  
  380. void
  381. RelocHunks(fi)
  382. FILE *fi;
  383. {
  384.     int n;
  385.     int dhno;
  386.     Hunk *h;
  387.     Hunk *dh;
  388.  
  389.     n = 0;
  390.     h = Hunks;
  391.  
  392.     while (n < NumHunks) {
  393.     long len;
  394.     long t;
  395.  
  396.     t = fgetl(fi);
  397.     switch(t) {
  398.     case 0x3EB:    /*  BSS     */
  399.         fgetl(fi);    /*  skip length */
  400.         break;
  401.     case 0x3E9:    /*  CODE    */
  402.     case 0x3EA:    /*  DATA    */
  403.         len = fgetl(fi) * 4;
  404.         fseek(fi, len, 1);
  405.         break;
  406.     case 0x3EC:    /*  HUNK_RELOC32    */
  407.         if (PIOpt) {
  408.         puts("32 bit relocations exist, cannot make position independant!");
  409.         exit(1);
  410.         }
  411.         while ((len = fgetl(fi)) != 0) {
  412.         dhno = fgetl(fi);    /*  hunk to relocate to */
  413.         if (dhno < FirstHunk || dhno >= NumHunks + FirstHunk) {
  414.             printf("hunk# in reloc32 bad: %d/%ld\n", dhno, NumHunks);
  415.             exit(1);
  416.         }
  417.         dh = Hunks + dhno - FirstHunk;
  418.         while (len) {        /*  offsets to relocate */
  419.             long off = fgetl(fi);
  420.  
  421.             if (off < 0 || off > h->Len - 4) {
  422.             printf("Bad offset: %ld len=%ld\n", off, h->Len);
  423.             exit(1);
  424.             }
  425.             *(long *)(h->Data + off) = ToMsbOrder(FromMsbOrder(*(long *)(h->Data + off)) + dh->Pc);
  426.             D(printf("Reloc in %d to %d offset %d add %04x\n", n, dhno, off, dh->Pc));
  427.             --len;
  428.         }
  429.         }
  430.         break;
  431.     case 0x3F0:    /*  SYMBOLS */
  432.         /*
  433.          *    ignore
  434.          */
  435.         while ((len = fgetl(fi)) != 0) {
  436.         ubyte type = len >> 24;
  437.  
  438.         len &= 0x00FFFFFF;
  439.         fseek(fi, len * 4, 1);
  440.  
  441.         switch(type) {
  442.         case 0:     /*  SYMB    */
  443.         case 1:     /*  DEF     */
  444.         case 2:     /*  ABS     */
  445.         case 3:     /*  RES     */
  446.             fgetl(fi);
  447.             break;
  448.         case 130:    /*  COMMON  */
  449.             puts("COMMON symbol not supported");
  450.             fgetl(fi);    /*  skip common size */
  451.             /* fall through */
  452.         case 129:    /*  REF32   */
  453.         case 131:    /*  REF16   */
  454.         case 132:    /*  REF8    */
  455.         case 134:    /*  REF16D  */
  456.                 /*  skip relocation info */
  457.             fseek(fi, fgetl(fi) * 4 + 4, 1);
  458.             break;
  459.         default:
  460.             printf("Symbol type %d unknown\n", type);
  461.             exit(1);
  462.         }
  463.         }
  464.         break;
  465.     case 0x3F2:    /*  ignore HUNK_END */
  466.         ++n;
  467.         ++h;
  468.         break;
  469.     default:
  470.         printf("Hunk type %08lx unknown\n", (unsigned long)h->Type);
  471.         exit(1);
  472.     }
  473.     }
  474. }
  475.  
  476. /*
  477.  *  Dump the stuff.  CODE is first, then DATA and finally BSS (yay!)
  478.  */
  479. void
  480. DumpHunks(fo1, fo2)
  481. FILE *fo1;
  482. FILE *fo2;
  483. {
  484.     long endpc = CodeStart;
  485.     short n;
  486.     short nextIsEven = 1;
  487.     Hunk *h;
  488.  
  489.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  490.     if (h->Type == 0x3E9) {
  491.         D(printf("$%04x bytes text @ %08lx\n", h->Len, h->Pc));
  492.         endpc = h->Pc + h->Len;
  493.         if (fo2) {
  494.         nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
  495.         } else {
  496.         fwrite(h->Data, 1, h->Len, fo1);
  497.         }
  498.     }
  499.     }
  500.  
  501.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  502.     if (h->Type == 0x3EA) {
  503.         D(printf("$%04x bytes data @ %08lx reloc to %08lx\n", h->Len, endpc, h->Pc));
  504.         endpc = h->Pc + h->Len;
  505.         if (fo2) {
  506.         nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
  507.         } else {
  508.         fwrite(h->Data, 1, h->Len, fo1);
  509.         }
  510.     }
  511.     }
  512.  
  513. #ifdef    BSS_IN_OUTPUT_FILE
  514.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  515.     if (h->Type == 0x3EB) {
  516.         D(printf("$%04x bytes bss  @ %08lx reloc to %08lx\n", h->Len, endpc, h->Pc));
  517.         endpc = h->Pc + h->Len;
  518.         if (fo2) {
  519.         nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
  520.         } else {
  521.         fwrite(h->Data, 1, h->Len, fo1);
  522.         }
  523.     }
  524.     }
  525.     D(printf("End at $%08lx\n", endpc));
  526. #endif
  527.  
  528. }
  529.  
  530.  
  531. long
  532. fgetl(fi)
  533. FILE *fi;
  534. {
  535.     long v;
  536.  
  537.     v = getc(fi) << 24;
  538.     v |= getc(fi) << 16;
  539.     v |= getc(fi) << 8;
  540.     v |= getc(fi);
  541.  
  542.     if (feof(fi)) {
  543.     puts("Unexpected EOF");
  544.     exit(1);
  545.     }
  546.     /*    D(printf("get %08x\n", v)); */
  547.     return(v);
  548. }
  549.  
  550. int
  551. fwrite_2(nextIsEven, fo_even, fo_odd, ptr, len)
  552. int nextIsEven;
  553. FILE *fo_even;
  554. FILE *fo_odd;
  555. char *ptr;
  556. long len;
  557. {
  558.     while (len--) {
  559.     if (nextIsEven)
  560.         putc(*ptr, fo_even);
  561.     else
  562.         putc(*ptr, fo_odd);
  563.     nextIsEven = 1 - nextIsEven;
  564.     ++ptr;
  565.     }
  566.     return(nextIsEven);
  567. }
  568.